package org.xxforest.game.core.scenes.scene2d.events;

import org.xxforest.game.core.XX;
import org.xxforest.game.core.scenes.scene2d.XXNode;
import org.xxforest.game.core.scenes.scene2d.XXPointerTouch;
import org.xxforest.game.core.scenes.scene2d.XXScreen;
import org.xxforest.game.core.scenes.scene2d.events.type.XXInputEvent;
import org.xxforest.game.core.scenes.scene2d.events.type.XXKeyPressEvent;
import org.xxforest.game.core.scenes.scene2d.events.type.XXTouchDragEvent;
import org.xxforest.game.core.scenes.scene2d.events.type.XXTouchEvent;

public class XXMotionHandler {
	
	private XXPointerTouch[] pointerTouchs = new XXPointerTouch[5] ;
	private XXNode lastTouchNode ;
	private float lastTouchSec ;
	
	private int [] pressKeys = new int [10];
	
	private XXScreen screen ;
	
	private XXMotionHandler(XXScreen screen){
		this.screen = screen ;
		for(int i = 0 ; i < pressKeys.length ; i++){
			pressKeys[i] = -1 ;
		}
		
		for(int i = 0 ; i < pointerTouchs.length ; i ++){
			pointerTouchs[i] = XXPointerTouch.create() ;
		}
	}
	
	public static XXMotionHandler create(XXScreen screen){
		return new XXMotionHandler(screen) ;
	}
	
	public void touchDown(int screenX, int screenY, float screenCoordsX, float screenCoordsY, int pointer, int button){
		if(pointer >= pointerTouchs.length)return ;
		
		XXNode node = screen.findHiter(screenCoordsX, screenCoordsY);
		if(node == null){
			node = screen ;
		}
		pointerTouchs[pointer].touch(screen,node,screenCoordsX, screenCoordsY,pointer,button);
		if(lastTouchNode == node && lastTouchSec < .3f){
			doubleClick(node,screenCoordsX,screenCoordsY);
		}
		
		lastTouchNode = node ;
		lastTouchSec = 0 ;
		
		if (node.hasEventListener(XXEventType.CLICK_DOWN)) {
			XXTouchEvent event = XXTouchEvent.create();
			event.clickDownEvent() ;
			event.setValues(node, screenCoordsX,screenCoordsY);
			node.fire(event);
			event.dispose();
		}
		
	}
	
	private void doubleClick(XXNode node, float screenCoordsX, float screenCoordsY) {
		if (node.hasEventListener(XXEventType.DOUBLE_CLICK)) {
			XXTouchEvent event = XXTouchEvent.create();
			event.doubleEvent() ;
			event.setValues(node, screenCoordsX,screenCoordsY);
			node.fire(event);
			event.dispose();
		}
	}

	public void touchUp(int screenX, int screenY, float screenCoordsX, float screenCoordsY, int pointer, int button){
		if(pointer >= pointerTouchs.length)return ;
		
		XXPointerTouch pointerTouch = pointerTouchs[pointer];
		pointerTouch.touchUp(screenCoordsX, screenCoordsY,pointer);
		XXNode focusNode = pointerTouch.getFocusNode();
		
		if (focusNode.hasEventListener(XXEventType.CLICK_UP)) {
			XXTouchEvent event = XXTouchEvent.create();
			event.clickUpEvent() ;
			event.setValues(focusNode, screenCoordsX,screenCoordsY);
			focusNode.fire(event);
			event.dispose();
		}
		
	}
	
	public void touchDragged(int screenX, int screenY, float screenCoordsX, float screenCoordsY, int pointer){
		if(pointer >= pointerTouchs.length)return ;
		
		XXPointerTouch pointerTouch = pointerTouchs[pointer];
		pointerTouch.drag(screenCoordsX, screenCoordsY,pointer);
		XXNode focusNode = pointerTouch.getFocusNode();
		
		if (focusNode.hasEventListener(XXEventType.TOUCHDRAGGED)) {
			XXTouchDragEvent event = XXTouchDragEvent.create();
			event.touchDrag(focusNode, pointerTouch);
			focusNode.fire(event);
			event.dispose();
		}
	}
	
	public void act(float delta){
		for(XXPointerTouch pointerTouch : pointerTouchs){
			if(pointerTouch.isTouchDown()){
				pointerTouch.alterDeltaTime(delta);
				//长按事件
				if(pointerTouch.getDeltaTime() >= 2f){
					longTouch(pointerTouch);
				}
			}
		}
		if(lastTouchSec < 10){
			lastTouchSec += delta ;
		}
		XXNode focusNode = XX.director.getFocus();
		if(focusNode != null && focusNode.hasEventListener(XXEventType.KEYPRESS)){
			XXKeyPressEvent keyPressEvent = XXKeyPressEvent.create(focusNode, pressKeys);
			focusNode.fire(keyPressEvent);
			keyPressEvent.dispose() ;
		}
	}

	private void longTouch(XXPointerTouch pointerTouch) {
		XXNode focusNode = pointerTouch.getFocusNode();
		if (focusNode.hasEventListener(XXEventType.LONG_TOUCH)) {
			XXTouchEvent event = XXTouchEvent.create();
			event.longTouchEvent() ;
			event.setValues(focusNode, pointerTouch.getToX(), pointerTouch.getToY());
			focusNode.fire(event);
			event.dispose();
		}
	}

	public boolean keyDown(int keyCode) {
		XXNode target = XX.director.getFocus();
		for(int i = 0 ; i < pressKeys.length ; i ++){
			if(pressKeys[i] == -1){
				pressKeys[i] = keyCode ;
				break ;
			}
		}
		if(target != null){
			XXInputEvent event = XXInputEvent.create();
			event.setScreen(screen);
			event.setType(XXEventType.KEYDOWN);
			event.setKeyCode(keyCode);
			boolean handled = target.fire(event);
			event.dispose() ;
			return handled ;
		}
		return false ;
	}

	public boolean keyUp(int keyCode) {
		XXNode target = XX.director.getFocus();
		for(int i = 0 ; i < pressKeys.length ; i ++){
			if(pressKeys[i] == keyCode){
				pressKeys[i] = -1 ;
			}
		}
		if(target != null){
			XXInputEvent event = XXInputEvent.create() ;
			event.setScreen(screen);
			event.setType(XXEventType.KEYUP);
			event.setKeyCode(keyCode);
			boolean handled = target.fire(event);
			event.dispose() ;
			return handled;
		}
		return false ;
	}

	public boolean keyTyped(char character) {
		XXNode target = XX.director.getFocus();
		if(target != null){
			XXInputEvent event = XXInputEvent.create() ;
			event.setScreen(screen);
			event.setType(XXEventType.KEYTYPED);
			event.setCharacter(character);
			boolean handled = target.fire(event);
			event.dispose() ;
			return handled;
		}
		return false ;
	}
	
}
